﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;

namespace EasyTrader.Manager
{
    using OpStateList = List<EasyTrader.Option.StateWatcher>;
    using PriceSignalList = List<EasyTrader.Signal.PriceSignal>;

    public class OptMainPriceSysManager : SysManager
    {
        // 옵션 주문은 현재 매수만 한다. 다만 상태에 따라 매수 주체만 다르게 바꿀 수 있다.
        public string FindOpOrderCode(int a_StateType)
        {
            string orderCode = "";

            EasyTrader.Option.CompVal firstCallBreakVal = null;
            // 풋의 최신 상태를 가져 온다.
            EasyTrader.Option.CompVal firstPutBreakVal = null;

            //Console.WriteLine("---> SysTime :: " + GlobalVar.DayIndexToTime(m_CurIndex).ToString());
            firstCallBreakVal = m_CallStateWatcher.GetFirstBreakVal("2");
            firstPutBreakVal = m_PutStateWatcher.GetFirstBreakVal("3");
            if (a_StateType == GlobalVar.SignalBuy)
            {
                if (firstCallBreakVal != null)
                {
                    if (firstCallBreakVal.Val > 5.0)
                        m_TotalSigMan.EasyTraderDataSet.DownLoader.GetCallUpDownCode(firstCallBreakVal.BreakCode, 1, out orderCode);
                    else
                        orderCode = firstCallBreakVal.BreakCode;
                }
            }
            else if (a_StateType == GlobalVar.SignalSell)
            {
                if (firstPutBreakVal != null)
                {
                    if (firstPutBreakVal.Val > 5.0)
                        m_TotalSigMan.EasyTraderDataSet.DownLoader.GetPutUpDownCode(firstCallBreakVal.BreakCode, -1, out orderCode);
                    else
                        orderCode = firstPutBreakVal.BreakCode;
                }
            }

            return orderCode;
        }



        // 코스피 200 신호
        private EasyTrader.Option.OptSignal m_K200Signal = new EasyTrader.Option.OptSignal();
        // 선물 신호
        private EasyTrader.Option.OptSignal m_FutSignal = new EasyTrader.Option.OptSignal();

        // 몇번째 청산인지를 기억하고 있다.
        private int m_LiqudLevel = 0;

        private void FindK200Signal(int a_CurIndex)
        {
            double open = 0.0, high = 0.0, low = 0.0, close = 0.0;
            Kospi2KOHLC(a_CurIndex, ref open, ref high, ref low, ref close);
            if (high != low)
            {
                double highLimit = 0.0;
                double lowLimit = 0.0;

                highLimit = open + GlobalVar.ErrorRange;
                lowLimit = open - GlobalVar.ErrorRange;
                if (open == high)
                {
                    if (close < lowLimit)
                    {
                        m_K200Signal.SigType = GlobalVar.OpSignalHighBegin;
                        m_K200Signal.OpenVal = open;
                    }
                }
                else if (open == low)
                {
                    if (close > highLimit)
                    {
                        m_K200Signal.SigType = GlobalVar.OpSignalLowBegin;
                        m_K200Signal.OpenVal = open;
                    }
                }
                else
                {
                    if (high <= highLimit && high >= open)
                    {
                        if (close < lowLimit)
                        {
                            m_K200Signal.SigType = GlobalVar.OpSignalHighBegin;
                            m_K200Signal.OpenVal = open;
                        }
                    }
                    else if (low <= open && low >= lowLimit)
                    {
                        if (close > highLimit)
                        {
                            m_K200Signal.SigType = GlobalVar.OpSignalLowBegin;
                            m_K200Signal.OpenVal = open;
                        }
                    }
                }
            }
        }

        private void FindFutSignal(int a_CurIndex)
        {
            double open = 0.0, high = 0.0, low = 0.0, close = 0.0;
            m_TotalSigMan.EasyTraderDataSet.GetFutOptOHLC(0, a_CurIndex, ref open, ref high, ref low, ref close);
            if (high != low)
            {
                double highLimit = 0.0;
                double lowLimit = 0.0;

                highLimit = open + GlobalVar.ErrorRange;
                lowLimit = open - GlobalVar.ErrorRange;
                if (open == high)
                {
                    if (close < lowLimit)
                    {
                        m_FutSignal.SigType = GlobalVar.OpSignalHighBegin;
                        m_FutSignal.OpenVal = open;
                    }
                }
                else if (open == low)
                {
                    if (close > highLimit)
                    {
                        m_FutSignal.SigType = GlobalVar.OpSignalLowBegin;
                        m_FutSignal.OpenVal = open;
                    }
                }
                else
                {
                    if (high <= highLimit && high >= open)
                    {
                        if (close < lowLimit)
                        {
                            m_FutSignal.SigType = GlobalVar.OpSignalHighBegin;
                            m_FutSignal.OpenVal = open;
                        }
                    }
                    else if (low <= open && low >= lowLimit)
                    {
                        if (close > highLimit)
                        {
                            m_FutSignal.SigType = GlobalVar.OpSignalLowBegin;
                            m_FutSignal.OpenVal = open;
                        }
                    }
                }
            }
        }

        private List<EasyTrader.DataSet.BarDataItem> m_K200List = new List<EasyTrader.DataSet.BarDataItem>();
        private bool m_K200ReadLock = false;

        private int m_CurIndex = 0;
        public int CurIndex
        {
            get { return m_CurIndex; }
            set { m_CurIndex = value; }
        }
        private EasyTrader.Option.StateWatcherList m_CallStateWatcher = new EasyTrader.Option.StateWatcherList(GlobalVar.OpCallMode);
        public EasyTrader.Option.StateWatcherList CallStateWatcher
        {
            get { return m_CallStateWatcher; }
            set { m_CallStateWatcher = value; }
        }
        private EasyTrader.Option.StateWatcherList m_PutStateWatcher = new EasyTrader.Option.StateWatcherList(GlobalVar.OpPutMode);
        public EasyTrader.Option.StateWatcherList PutStateWatcher
        {
            get { return m_PutStateWatcher; }
            set { m_PutStateWatcher = value; }
        }
        private bool m_StatePrepared = false;

        public void ClearBreakVal()
        {
            m_CallStateWatcher.ClearBreakVal();
            m_PutStateWatcher.ClearBreakVal();
        }

        public void PrepareState()
        {
            if (m_StatePrepared == false && GlobalVar.AllDataDownloaded == true)
            {
                CreateStateList(m_TotalSigMan.EasyTraderDataSet.OptChartTableList);
                FillComVal(Convert.ToInt32(m_TotalSigMan.EasyTraderDataSet.DownLoader.CurDay));
                m_StatePrepared = true;
            }
        }
        // 비교할 값들을 채워 넣는다.
        // 여기에는 월고, 월저, 기준가, 마디가, 목표가가 해당된다.
        private void FillComVal(int a_Date)
        {
            m_CallStateWatcher.Date = a_Date;
            m_PutStateWatcher.Date = a_Date;
            OpStateList stateList = m_CallStateWatcher.StateList;
            for (int i = 0; i < stateList.Count; i++)
            {
                EasyTrader.Option.StateWatcher watcher = stateList[i];
                watcher.ResetDDEInfo(a_Date, m_TotalSigMan);
            }

            stateList = m_PutStateWatcher.StateList;
            for (int i = 0; i < stateList.Count; i++)
            {
                EasyTrader.Option.StateWatcher watcher = stateList[i];
                watcher.ResetDDEInfo(a_Date, m_TotalSigMan);
            }
        }

        // 콜과 풋의 상태 목록을 만들고 초기화 한다.
        // 현재 데이터를 얻어 오는 차트 목록을 기반으로 한다. 
        private void CreateStateList(List<EasyTrader.DataSet.BarDataTable> a_SourceTableList)
        {
            // 일단 모든 상태 목록을 없애 준다.
            m_CallStateWatcher.StateList.Clear();
            m_PutStateWatcher.StateList.Clear();

            for (int i = 0; i < a_SourceTableList.Count; i++)
            {
                EasyTrader.DataSet.BarDataTable table = a_SourceTableList[i];
                string opCode = table.TableName;
                string sideCode = opCode.Substring(0, 1);
                if (sideCode == "2")
                {
                    // 낮은 행사가 먼저 추가되어 높은 값이 나중에 추가됨
                    EasyTrader.Option.StateWatcher stateWatcher = new EasyTrader.Option.StateWatcher();
                    stateWatcher.CreateTypicalValList();
                    stateWatcher.OpCode = opCode;
                    stateWatcher.Table = table;
                    stateWatcher.EasyTraderDataSet = m_TotalSigMan.EasyTraderDataSet;
                    stateWatcher.Parent = m_CallStateWatcher;
                    m_CallStateWatcher.StateList.Add(stateWatcher);
                }
                else if (sideCode == "3")
                {
                    // 낮은 행사가가 먼저 추가되어 높은 행사가가 나중에 추가됨.
                    EasyTrader.Option.StateWatcher stateWatcher = new EasyTrader.Option.StateWatcher();
                    stateWatcher.CreateTypicalValList();
                    stateWatcher.OpCode = opCode;
                    stateWatcher.Table = table;
                    stateWatcher.EasyTraderDataSet = m_TotalSigMan.EasyTraderDataSet;
                    stateWatcher.Parent = m_PutStateWatcher;
                    m_PutStateWatcher.StateList.Add(stateWatcher);
                }
            }
        }


        private void FindCurState()
        {
            //return m_TotalSigMan.FindState(m_SysType, m_FirstSig, m_PriceStateList, m_LogFileName, ref m_CurState);
            // 시스템 상태를 확인한다.
            EasyTrader.Signal.PriceSignal curState = FindSysState();
            // 시스템 상태가 바뀌었을 경우 확인하고 신호정보를 복사하여 추가한다.
            m_TotalSigMan.CheckAddState(m_CurIndex, m_PriceStateList, curState);
        }

        private void SetSigState(ref EasyTrader.Signal.PriceSignal a_Signal, EasyTrader.Option.CompVal a_CallVal, EasyTrader.Option.CompVal a_PutVal)
        {
            if (a_Signal == null)
                return;

            if (a_CallVal != null)
            {
                a_Signal.CallVal = a_CallVal.Val;
                a_Signal.CallType = a_CallVal.Type;
                a_Signal.CallState = a_CallVal.RecentState;
                a_Signal.CallCode = a_CallVal.Watcher.OpCode;
                a_Signal.CallBreakTime = a_CallVal.RecentBreakTime;
            }

            if (a_PutVal != null)
            {
                a_Signal.PutVal = a_PutVal.Val;
                a_Signal.PutType = a_PutVal.Type;
                a_Signal.PutState = a_PutVal.RecentState;
                a_Signal.PutCode = a_PutVal.Watcher.OpCode;
                a_Signal.PutBreakTime = a_PutVal.RecentBreakTime;
            }
        }

        private void SetSigState(ref EasyTrader.Signal.PriceSignal a_Signal, EasyTrader.Option.CompVal a_CallVal, EasyTrader.Option.CompVal a_PutVal, int a_SigType)
        {
            if (a_Signal == null)
                return;

            if (a_CallVal != null)
            {
                a_Signal.CallVal = a_CallVal.Val;
                a_Signal.CallType = a_CallVal.Type;
                a_Signal.CallState = a_CallVal.RecentState;
                a_Signal.CallCode = a_CallVal.Watcher.OpCode;
                a_Signal.CallBreakTime = a_CallVal.RecentBreakTime;
            }

            if (a_PutVal != null)
            {
                a_Signal.PutVal = a_PutVal.Val;
                a_Signal.PutType = a_PutVal.Type;
                a_Signal.PutState = a_PutVal.RecentState;
                a_Signal.PutCode = a_PutVal.Watcher.OpCode;
                a_Signal.PutBreakTime = a_PutVal.RecentBreakTime;
            }

        }

        // 붕괴되는 값들을 모아 놓는다.
        // 만약 붕괴되었던 값이 돌파를 할 경우는 붕괴 목록에서 제외해준다.
        // 따라서 이 목록에는 항상 붕괴된 목록만 존재하게 한다.
        private void CollectPutTargetValues(EasyTrader.Option.CompVal a_BreakVal)
        {
            ;
        }

        // 붕괴되는 값들을 모아 놓는다.
        private void CollectCallTargetValues(EasyTrader.Option.CompVal a_BreakVal)
        {
            ;
        }

        private void Kospi2KOHLC(int a_CurIndex, ref double a_Open, ref double a_High, ref double a_Low, ref double a_Close)
        {
            if (m_K200List.Count == 0)
                return;

            EasyTrader.DataSet.BarDataItem item = m_K200List[0];

            a_Open = Convert.ToDouble(item.Open.ToString());
            a_High = Convert.ToDouble(item.High.ToString());
            a_Low = Convert.ToDouble(item.Low.ToString());
            a_Close = Convert.ToDouble(item.Close.ToString());

            for (int i = 0; i < m_K200List.Count; i++)
            {
                item = m_K200List[i];
                double high = Convert.ToDouble(item.High.ToString());
                double low = Convert.ToDouble(item.Low.ToString());
                double close = Convert.ToDouble(item.Close.ToString());
                a_Close = close;
                if (high > a_High)
                    a_High = high;
                if (low < a_Low)
                    a_Low = low;
                if (i == a_CurIndex)
                    break;
            }
        }


        

        // 시간이 같으면 고가와 저가 종가만 갱신해 준다.
        public void ReadKospi200(string a_Date)
        {
            if (m_K200ReadLock == true)
                return;

            m_K200ReadLock = true;

            string fileName = GlobalVar.K200Dir;//Directory.GetCurrentDirectory();
            //fileName += "C:\\Kospi200.txt";
            if (File.Exists(fileName))
            {
                using (StreamReader sr = new StreamReader(fileName))
                {
                    //sr.BaseStream.Seek(1024, SeekOrigin.Current);
                    while (sr.Peek() >= 0)
                    {
                        string opCrossData = sr.ReadLine();
                        string[] words = opCrossData.Split(' ');
                        string[] data = new string[3];
                        for (int i = 0, j = 0; i < words.Length; i++)
                        {
                            if (words[i] != "")
                            {
                                data[j] = words[i];
                                j++;
                            }
                        }

                        string dates = data[0];
                        string[] date = dates.Split('-');
                        dates = date[0] + date[1] + date[2];
                        string times = data[1];
                        string[] time = times.Split(':');
                        times = time[0] + time[1];
                        string val = data[2];


                        string[] values = val.Split(',');

                        string open = values[0];
                        string high = values[1];
                        string low = values[2];
                        string close = values[3];

                        if (a_Date == dates)
                        {
                            int i = 0;
                            i = i + 1;
                            EasyTrader.DataSet.BarDataItem newItem = null;
                            if (m_K200List.Count > 0)
                            {
                                EasyTrader.DataSet.BarDataItem lastItem = m_K200List[m_K200List.Count - 1];
                                if (lastItem.Time.ToString() == times)
                                {
                                    Console.WriteLine("Same lastitem time " + lastItem.Time.ToString());
                                    Console.WriteLine("Same curtitem time " + times);

                                    // 고가, 저가, 종가만 갱신해 준다.
                                    lastItem.Close = close;
                                    if (Convert.ToDouble(high) > Convert.ToDouble(lastItem.High))
                                    {
                                        lastItem.High = high;
                                    }
                                    if (Convert.ToDouble(low) < Convert.ToDouble(lastItem.Low))
                                    {
                                        lastItem.Low = low;
                                    }
                                }
                                else
                                {
                                    Console.WriteLine("Dif lastitem time " + lastItem.Time.ToString());
                                    Console.WriteLine("Dif curtitem time " + times);
                                    if (Convert.ToInt32(lastItem.Time) < Convert.ToInt32(times))
                                    {
                                        newItem = new EasyTrader.DataSet.BarDataItem();
                                        newItem.Date = dates;
                                        newItem.Time = times;
                                        newItem.Open = open;
                                        newItem.High = high;
                                        newItem.Low = low;
                                        newItem.Close = close;
                                        m_K200List.Add(newItem);
                                    }
                                }
                            }
                            else
                            {
                                newItem = new EasyTrader.DataSet.BarDataItem();
                                newItem.Date = dates;
                                newItem.Time = times;
                                newItem.Open = open;
                                newItem.High = high;
                                newItem.Low = low;
                                newItem.Close = close;
                                m_K200List.Add(newItem);
                            }
                        }
                    }
                }
            }

            m_K200ReadLock = false;
        }

        private double FindLiqPoint(int a_CurIndex, string a_OpCode, int a_State, int a_LiqLevel)
        {
            int q = (int)((a_LiqLevel + 1) / 2.0);
            int q2 = a_LiqLevel % 2;
            // 장상승시 콜은 자기보다 내가의 저가가 목표
            // 장상승시 풋은 자기보다 외가의 고가가 목표 - 외가는 신뢰성이 떨어지므로 내가만 조사를 한다.
            if (a_State == GlobalVar.SignalBuy)
            {
                // 상승 중이므로 콜의 내가를 찾아서 목표값을 찾아 준다.
                string opCode = "";
                m_TotalSigMan.EasyTraderDataSet.DownLoader.GetCallUpDownCode(a_OpCode, -q, out opCode);
                EasyTrader.Option.StateWatcher curStateWatcher = m_CallStateWatcher.FindStateWatcher(a_OpCode);
                EasyTrader.Option.StateWatcher innerStateWatcher = m_CallStateWatcher.FindStateWatcher(opCode);
                double curOpen = 0.0, curHigh = 0.0, curLow = 0.0, curClose = 0.0, innerOpen = 0.0, innerHigh = 0.0, innerLow = 0.0, innerClose = 0.0;
                curStateWatcher.GetOHLC(0, a_CurIndex, ref curOpen, ref curHigh, ref curLow, ref curClose);
                innerStateWatcher.GetOHLC(0, a_CurIndex, ref innerOpen, ref innerHigh, ref innerLow, ref innerClose);
                // 짝수번째의 청산일 경우 - 저가를 그냥 반환한다.
                if (q2 == 0)
                {
                    return innerLow;
                }
                else // 홀수 번째는 현재와 찾은 행사가의 저가를 각각 더하여 평균값을 반환해 준다.
                {
                    return (curLow + innerLow) / 2.0;
                }
            }
            else if (a_State == GlobalVar.SignalSell)
            {
                // 하락 중이므로 풋의 내가를 찾아서 목표값을 찾아 준다.
                string opCode = "";
                m_TotalSigMan.EasyTraderDataSet.DownLoader.GetPutUpDownCode(a_OpCode, q, out opCode);
                EasyTrader.Option.StateWatcher curStateWatcher = m_PutStateWatcher.FindStateWatcher(a_OpCode);
                EasyTrader.Option.StateWatcher innerStateWatcher = m_PutStateWatcher.FindStateWatcher(opCode);
                double curOpen = 0.0, curHigh = 0.0, curLow = 0.0, curClose = 0.0, innerOpen = 0.0, innerHigh = 0.0, innerLow = 0.0, innerClose = 0.0;
                curStateWatcher.GetOHLC(0, a_CurIndex, ref curOpen, ref curHigh, ref curLow, ref curClose);
                innerStateWatcher.GetOHLC(0, a_CurIndex, ref innerOpen, ref innerHigh, ref innerLow, ref innerClose);
                // 짝수번째의 청산일 경우 - 저가를 그냥 반환한다.
                if (q2 == 0)
                {
                    return innerLow;
                }
                else // 홀수 번째는 현재와 찾은 행사가의 저가를 각각 더하여 평균값을 반환해 준다.
                {
                    return (curLow + innerLow) / 2.0;
                }
            }

            return 0.0;
        }

        /*
        private int FindLiqSignal(int a_CurIndex, string a_OpCode, int a_State, int a_LiqLevel)
        {
            int q = (int)((a_LiqLevel + 1) / 2.0);
            int q2 = a_LiqLevel % 2;
            double liqPoint = 0.0;
            int sigType = GlobalVar.SignalNone;

            // 장상승시 콜은 자기보다 내가의 저가가 목표
            // 장상승시 풋은 자기보다 외가의 고가가 목표 - 외가는 신뢰성이 떨어지므로 내가만 조사를 한다.
            if (a_State == GlobalVar.SignalBuy)
            {
                // 상승 중이므로 콜의 내가를 찾아서 목표값을 찾아 준다.
                // 콜의 내가는 행사값이 낮은 데서 찾아야 하므로 레벨을 낮춰서 찾아온다.
                string innerCode = "";
                m_TotalSigMan.EasyTraderDataSet.DownLoader.GetCallUpDownCode(a_OpCode, -(q - 1), out innerCode);
                EasyTrader.Option.StateWatcher curStateWatcher = m_CallStateWatcher.FindStateWatcher(innerCode);
                m_TotalSigMan.EasyTraderDataSet.DownLoader.GetCallUpDownCode(a_OpCode, -q, out innerCode);
                EasyTrader.Option.StateWatcher innerStateWatcher = m_CallStateWatcher.FindStateWatcher(innerCode);
                double curOpen = 0.0, curHigh = 0.0, curLow = 0.0, curClose = 0.0, innerOpen = 0.0, innerHigh = 0.0, innerLow = 0.0, innerClose = 0.0;
                curStateWatcher.GetOHLC(0, a_CurIndex, ref curOpen, ref curHigh, ref curLow, ref curClose);
                innerStateWatcher.GetOHLC(0, a_CurIndex, ref innerOpen, ref innerHigh, ref innerLow, ref innerClose);
                // 짝수번째의 청산일 경우 - 저가를 그냥 반환한다.
                if (q2 == 0)
                {
                    liqPoint = innerLow;
                    int result = innerStateWatcher.FindRecentBreakIn(m_CurIndex, liqPoint);
                    if (result == GlobalVar.FromDown)
                        sigType = GlobalVar.SignalBuyPartialLiquid;
                }
                else // 홀수 번째는 현재와 찾은 행사가의 저가를 각각 더하여 평균값을 반환해 준다.
                {
                    liqPoint = (curLow + innerLow) / 2.0;
                    int result = curStateWatcher.FindRecentBreakIn(m_CurIndex, liqPoint);
                    if (result == GlobalVar.FromDown)
                        sigType = GlobalVar.SignalBuyPartialLiquid;
                }
            }
            else if (a_State == GlobalVar.SignalSell)
            {
                // 하락 중이므로 풋의 내가를 찾아서 목표값을 찾아 준다.
                // 풋의 내가는 행사가가 높아야 함으로 레벨을 높여서 찾아 온다.
                string innerCode = "";
                m_TotalSigMan.EasyTraderDataSet.DownLoader.GetPutUpDownCode(a_OpCode, (q - 1), out innerCode);
                EasyTrader.Option.StateWatcher curStateWatcher = m_PutStateWatcher.FindStateWatcher(innerCode);
                m_TotalSigMan.EasyTraderDataSet.DownLoader.GetPutUpDownCode(a_OpCode, q, out innerCode);
                EasyTrader.Option.StateWatcher innerStateWatcher = m_PutStateWatcher.FindStateWatcher(innerCode);
                double curOpen = 0.0, curHigh = 0.0, curLow = 0.0, curClose = 0.0, innerOpen = 0.0, innerHigh = 0.0, innerLow = 0.0, innerClose = 0.0;
                curStateWatcher.GetOHLC(0, a_CurIndex, ref curOpen, ref curHigh, ref curLow, ref curClose);
                innerStateWatcher.GetOHLC(0, a_CurIndex, ref innerOpen, ref innerHigh, ref innerLow, ref innerClose);
                // 짝수번째의 청산일 경우 - 저가를 그냥 반환한다.
                if (q2 == 0)
                {
                    liqPoint = innerLow;
                    int result = innerStateWatcher.FindRecentBreakIn(m_CurIndex, liqPoint);
                    if (result == GlobalVar.FromDown)
                        sigType = GlobalVar.SignalSellPartialLiquid;
                }
                else // 홀수 번째는 현재와 찾은 행사가의 저가를 각각 더하여 평균값을 반환해 준다.
                {
                    liqPoint = (curLow + innerLow) / 2.0;
                    int result = curStateWatcher.FindRecentBreakIn(m_CurIndex, liqPoint);
                    if (result == GlobalVar.FromDown)
                        sigType = GlobalVar.SignalSellPartialLiquid;
                }
            }

            return sigType;
        }
        */

        // 외가에 의한 청산
        private int FindLiqSignalByOuterVal(int a_CurIndex, string a_OpCode, int a_State, int a_LiqLevel)
        {
            int q = (int)((a_LiqLevel + 1) / 2.0);
            int q2 = a_LiqLevel % 2;
            double liqPoint = 0.0;
            int sigType = GlobalVar.SignalNone;
            string sideCode = a_OpCode.Substring(0, 1);

            // 장상승시 콜은 자기보다 내가의 저가가 목표
            // 장상승시 풋은 자기보다 외가의 고가가 목표 - 외가는 신뢰성이 떨어지므로 내가만 조사를 한다.
            if (a_State == GlobalVar.SignalBuy && sideCode == "3")
            {
                // 상승 중이므로 풋의 외가를 찾아서 목표값을 찾아 준다.
                // 풋은 행사가가 낮은 것이 외가 이므로 
                string innerCode = "";
                m_TotalSigMan.EasyTraderDataSet.DownLoader.GetPutUpDownCode(a_OpCode, -(q - 1), out innerCode);
                EasyTrader.Option.StateWatcher curStateWatcher = m_PutStateWatcher.FindStateWatcher(innerCode);
                m_TotalSigMan.EasyTraderDataSet.DownLoader.GetPutUpDownCode(a_OpCode, -q, out innerCode);
                EasyTrader.Option.StateWatcher innerStateWatcher = m_PutStateWatcher.FindStateWatcher(innerCode);
                double curOpen = 0.0, curHigh = 0.0, curLow = 0.0, curClose = 0.0, innerOpen = 0.0, innerHigh = 0.0, innerLow = 0.0, innerClose = 0.0;
                curStateWatcher.GetOHLC(0, a_CurIndex, ref curOpen, ref curHigh, ref curLow, ref curClose);
                innerStateWatcher.GetOHLC(0, a_CurIndex, ref innerOpen, ref innerHigh, ref innerLow, ref innerClose);
                // 짝수번째의 청산일 경우 - 저가를 그냥 반환한다.
                if (q2 == 0)
                {
                    liqPoint = innerLow;
                    int result = innerStateWatcher.FindRecentBreakIn(m_CurIndex, liqPoint);
                    if (result == GlobalVar.FromDown)
                        sigType = GlobalVar.SignalBuyPartialLiquid;
                }
                else // 홀수 번째는 현재와 찾은 행사가의 저가를 각각 더하여 평균값을 반환해 준다.
                {
                    liqPoint = (curLow + innerLow) / 2.0;
                    int result = curStateWatcher.FindRecentBreakIn(m_CurIndex, liqPoint);
                    if (result == GlobalVar.FromDown)
                        sigType = GlobalVar.SignalBuyPartialLiquid;
                }
            }
            else if (a_State == GlobalVar.SignalSell && sideCode == "2")
            {
                // 하락 중이므로 콜의 외가를 찾아서 목표값을 찾아 준다.
                // 콜의 외가는 행사가가 높아야 함으로 레벨을 높여서 찾아 온다.
                string innerCode = "";
                m_TotalSigMan.EasyTraderDataSet.DownLoader.GetCallUpDownCode(a_OpCode, (q - 1), out innerCode);
                EasyTrader.Option.StateWatcher curStateWatcher = m_CallStateWatcher.FindStateWatcher(innerCode);
                m_TotalSigMan.EasyTraderDataSet.DownLoader.GetCallUpDownCode(a_OpCode, q, out innerCode);
                EasyTrader.Option.StateWatcher innerStateWatcher = m_CallStateWatcher.FindStateWatcher(innerCode);
                double curOpen = 0.0, curHigh = 0.0, curLow = 0.0, curClose = 0.0, innerOpen = 0.0, innerHigh = 0.0, innerLow = 0.0, innerClose = 0.0;
                curStateWatcher.GetOHLC(0, a_CurIndex, ref curOpen, ref curHigh, ref curLow, ref curClose);
                innerStateWatcher.GetOHLC(0, a_CurIndex, ref innerOpen, ref innerHigh, ref innerLow, ref innerClose);
                // 짝수번째의 청산일 경우 - 저가를 그냥 반환한다.
                if (q2 == 0)
                {
                    liqPoint = innerLow;
                    int result = innerStateWatcher.FindRecentBreakIn(m_CurIndex, liqPoint);
                    if (result == GlobalVar.FromDown)
                        sigType = GlobalVar.SignalSellPartialLiquid;
                }
                else // 홀수 번째는 현재와 찾은 행사가의 저가를 각각 더하여 평균값을 반환해 준다.
                {
                    liqPoint = (curLow + innerLow) / 2.0;
                    int result = curStateWatcher.FindRecentBreakIn(m_CurIndex, liqPoint);
                    if (result == GlobalVar.FromDown)
                        sigType = GlobalVar.SignalSellPartialLiquid;
                }
            }

            return sigType;
        }


        // 내가에 의한 청산
        private int FindLiqSignalByInnderVal(int a_CurIndex, string a_OpCode, int a_State, int a_LiqLevel)
        {
            int q = (int)((a_LiqLevel + 1) / 2.0);
            int q2 = a_LiqLevel % 2;
            double liqPoint = 0.0;
            int sigType = GlobalVar.SignalNone;
            string sideCode = a_OpCode.Substring(0, 1);
            // 장상승시 콜은 자기보다 내가의 저가가 목표
            // 장상승시 풋은 자기보다 외가의 고가가 목표 - 외가는 신뢰성이 떨어지므로 내가만 조사를 한다.
            if (a_State == GlobalVar.SignalBuy && sideCode == "2")
            {
                // 상승 중이므로 콜의 내가를 찾아서 목표값을 찾아 준다.
                // 콜의 내가는 행사값이 낮은 데서 찾아야 하므로 레벨을 낮춰서 찾아온다.
                string innerCode = "";
                m_TotalSigMan.EasyTraderDataSet.DownLoader.GetCallUpDownCode(a_OpCode, -(q - 1), out innerCode);
                EasyTrader.Option.StateWatcher curStateWatcher = m_CallStateWatcher.FindStateWatcher(innerCode);
                m_TotalSigMan.EasyTraderDataSet.DownLoader.GetCallUpDownCode(a_OpCode, -q, out innerCode);
                EasyTrader.Option.StateWatcher innerStateWatcher = m_CallStateWatcher.FindStateWatcher(innerCode);
                double curOpen = 0.0, curHigh = 0.0, curLow = 0.0, curClose = 0.0, innerOpen = 0.0, innerHigh = 0.0, innerLow = 0.0, innerClose = 0.0;
                curStateWatcher.GetOHLC(0, a_CurIndex, ref curOpen, ref curHigh, ref curLow, ref curClose);
                innerStateWatcher.GetOHLC(0, a_CurIndex, ref innerOpen, ref innerHigh, ref innerLow, ref innerClose);
                // 짝수번째의 청산일 경우 - 저가를 그냥 반환한다.
                if (q2 == 0)
                {
                    liqPoint = innerLow;
                    int result = innerStateWatcher.FindRecentBreakIn(m_CurIndex, liqPoint);
                    if (result == GlobalVar.FromDown)
                        sigType = GlobalVar.SignalBuyPartialLiquid;
                }
                else // 홀수 번째는 현재와 찾은 행사가의 저가를 각각 더하여 평균값을 반환해 준다.
                {
                    liqPoint = (curLow + innerLow) / 2.0;
                    int result = curStateWatcher.FindRecentBreakIn(m_CurIndex, liqPoint);
                    if (result == GlobalVar.FromDown)
                        sigType = GlobalVar.SignalBuyPartialLiquid;
                }
            }
            else if (a_State == GlobalVar.SignalSell && sideCode == "3")
            {
                // 하락 중이므로 풋의 내가를 찾아서 목표값을 찾아 준다.
                // 풋의 내가는 행사가가 높아야 함으로 레벨을 높여서 찾아 온다.
                string innerCode = "";
                m_TotalSigMan.EasyTraderDataSet.DownLoader.GetPutUpDownCode(a_OpCode, (q - 1), out innerCode);
                EasyTrader.Option.StateWatcher curStateWatcher = m_PutStateWatcher.FindStateWatcher(innerCode);
                m_TotalSigMan.EasyTraderDataSet.DownLoader.GetPutUpDownCode(a_OpCode, q, out innerCode);
                EasyTrader.Option.StateWatcher innerStateWatcher = m_PutStateWatcher.FindStateWatcher(innerCode);
                double curOpen = 0.0, curHigh = 0.0, curLow = 0.0, curClose = 0.0, innerOpen = 0.0, innerHigh = 0.0, innerLow = 0.0, innerClose = 0.0;
                curStateWatcher.GetOHLC(0, a_CurIndex, ref curOpen, ref curHigh, ref curLow, ref curClose);
                innerStateWatcher.GetOHLC(0, a_CurIndex, ref innerOpen, ref innerHigh, ref innerLow, ref innerClose);
                // 짝수번째의 청산일 경우 - 저가를 그냥 반환한다.
                if (q2 == 0)
                {
                    liqPoint = innerLow;
                    int result = innerStateWatcher.FindRecentBreakIn(m_CurIndex, liqPoint);
                    if (result == GlobalVar.FromDown)
                        sigType = GlobalVar.SignalSellPartialLiquid;
                }
                else // 홀수 번째는 현재와 찾은 행사가의 저가를 각각 더하여 평균값을 반환해 준다.
                {
                    liqPoint = (curLow + innerLow) / 2.0;
                    int result = curStateWatcher.FindRecentBreakIn(m_CurIndex, liqPoint);
                    if (result == GlobalVar.FromDown)
                        sigType = GlobalVar.SignalSellPartialLiquid;
                }
            }

            return sigType;
        }

        private EasyTrader.Signal.PriceSignal FindSysState()
        {
            EasyTrader.Signal.PriceSignal lastState = m_TotalSigMan.GetLastSignal(m_PriceStateList);

            int stateCount = m_PriceStateList.Count;
            // 기존 파일을 지운다.
            //DeleteKosip200File();

            if (lastState == null)
            {
                // 코스피 200 지수를 읽어 온다.
                ReadKospi200(m_TotalSigMan.EasyTraderDataSet.DownLoader.CurDay.ToString());
            }
            
            

            // 선물 신호 확인
            FindFutSignal(m_CurIndex);
            // 코스피 200 신호 확인 - 진입이 일단 이루어진 이후에 확인차원에서 사용한다.
            FindK200Signal(m_CurIndex);
            
            // 콜과 풋의 개별 상태를 갱신해 준다.
            OpStateList stateList = m_CallStateWatcher.StateList;
            for (int i = 0; i < stateList.Count; i++)
            {
                // 낮은 행사가 부터 먼저 조사하고 있음
                EasyTrader.Option.StateWatcher watcher = stateList[i];
                int curDate = Convert.ToInt32(m_TotalSigMan.EasyTraderDataSet.DownLoader.CurDay);
                // 테이블과 dde 값이 일치하지 않으면 일치시켜 준다.
                watcher.CheckTableSync(curDate, m_TotalSigMan);
                // 현재 상태로 갱신해 준다.
                string sideCode = watcher.OpCode.Substring(0, 1);
                if (sideCode == "2")
                    watcher.FindOHLSignal(m_CurIndex);
            }

            stateList = m_PutStateWatcher.StateList;
            for (int i = 0; i < stateList.Count; i++)
            {
                // 낮은 행사가 부터 먼저 조사하고 있음
                EasyTrader.Option.StateWatcher watcher = stateList[i];
                int curDate = Convert.ToInt32(m_TotalSigMan.EasyTraderDataSet.DownLoader.CurDay);
                // 테이블과 dde 값이 일치하지 않으면 일치시켜 준다.
                watcher.CheckTableSync(curDate, m_TotalSigMan);
                // 현재 상태로 갱신해 준다.
                string sideCode = watcher.OpCode.Substring(0, 1);
                if (sideCode == "3")
                    watcher.FindOHLSignal(m_CurIndex);
            }

            if (lastState != null)
            {
                // 콜과 풋의 개별 상태를 갱신해 준다.
                stateList = m_CallStateWatcher.StateList;
                for (int i = 0; i < stateList.Count; i++)
                {
                    // 낮은 행사가 부터 먼저 조사하고 있음
                    EasyTrader.Option.StateWatcher watcher = stateList[i];
                    // 현재 상태로 갱신해 준다.
                    string sideCode = watcher.OpCode.Substring(0, 1);
                    if (sideCode == "2")
                        watcher.FindBreakHighLow(m_CurIndex);
                }

                stateList = m_PutStateWatcher.StateList;
                for (int i = 0; i < stateList.Count; i++)
                {
                    // 낮은 행사가 부터 먼저 조사하고 있음
                    EasyTrader.Option.StateWatcher watcher = stateList[i];
                    // 현재 상태로 갱신해 준다.
                    string sideCode = watcher.OpCode.Substring(0, 1);
                    if (sideCode == "3")
                        watcher.FindBreakHighLow(m_CurIndex);
                }
                // 매수일 경우
                if (lastState.Type == GlobalVar.SignalBuy)
                {
                    // 매수 상태에서 높은 곳에서 시작했다는 표시가 있을 때
                    if (m_K200Signal.SigType == GlobalVar.OpSignalHighBegin)
                    {
                        // 매수 청산
                        m_TotalSigMan.SetSignalInfo(m_PriceStateList.Count, GlobalVar.SignalExitBuy, GlobalVar.SignalStateLiquid, ref m_CurState);
                        m_TotalSigMan.WriteSignalLog("매수 청산 신호 발생", m_LogFileName, m_CurState);
                        SetSigState(ref m_CurState, null, null);
                        return m_CurState;
                    }
                    int callCount = m_CallStateWatcher.CheckUnderLowCount();
                    int putCount = m_PutStateWatcher.CheckOverHighCount();
                    if (callCount + putCount > 0)
                    {
                        // 매수 청산
                        m_TotalSigMan.SetSignalInfo(m_PriceStateList.Count, GlobalVar.SignalExitBuy, GlobalVar.SignalStateLiquid, ref m_CurState);
                        m_TotalSigMan.WriteSignalLog("매수 청산 신호 발생", m_LogFileName, m_CurState);
                        SetSigState(ref m_CurState, null, null);
                        return m_CurState;
                    }
                    EasyTrader.Option.OptSignal firstCallSignal = m_CallStateWatcher.GetFirstLowBeginSignal();
                    EasyTrader.Option.OptSignal firstPutSignal = m_PutStateWatcher.GetFirstHighBeginSignal();
                    int LiqSignal = FindLiqSignalByOuterVal(m_CurIndex, firstCallSignal.Code, lastState.Type, m_LiqudLevel + 1);
                    if (LiqSignal == GlobalVar.SignalBuyPartialLiquid)
                    {
                        // 매수 부분 익절
                        m_TotalSigMan.SetSignalInfo(m_PriceStateList.Count, GlobalVar.SignalBuyPartialLiquid, GlobalVar.SignalStateLiquid, ref m_CurState);
                        m_TotalSigMan.WriteSignalLog("매수 부분 청산 신호 발생", m_LogFileName, m_CurState);
                        SetSigState(ref m_CurState, null, null);
                        return m_CurState;
                    }
                }
                else if (lastState.Type == GlobalVar.SignalSell)
                {
                    // 매도인데 낮은 상태에서 시작했다는 표시가 있을 때
                    if (m_K200Signal.SigType == GlobalVar.OpSignalLowBegin)
                    {
                        // 매도 청산
                        m_TotalSigMan.SetSignalInfo(m_PriceStateList.Count, GlobalVar.SignalExitSell, GlobalVar.SignalStateLiquid, ref m_CurState);
                        m_TotalSigMan.WriteSignalLog("매도 청산 신호 발생", m_LogFileName, m_CurState);
                        SetSigState(ref m_CurState, null, null);
                        return m_CurState;
                    }
                    int callCount = m_CallStateWatcher.CheckOverHighCount();
                    int putCount = m_PutStateWatcher.CheckUnderLowCount();
                    if (callCount + putCount > 0)
                    {
                        // 매도 청산
                        m_TotalSigMan.SetSignalInfo(m_PriceStateList.Count, GlobalVar.SignalExitSell, GlobalVar.SignalStateLiquid, ref m_CurState);
                        m_TotalSigMan.WriteSignalLog("매도 청산 신호 발생", m_LogFileName, m_CurState);
                        SetSigState(ref m_CurState, null, null);
                        return m_CurState;
                    }

                    EasyTrader.Option.OptSignal firstCallSignal = m_CallStateWatcher.GetFirstHighBeginSignal();
                    EasyTrader.Option.OptSignal firstPutSignal = m_PutStateWatcher.GetFirstLowBeginSignal();
                    int LiqSignal = FindLiqSignalByOuterVal(m_CurIndex, firstPutSignal.Code, lastState.Type, m_LiqudLevel + 1);
                    if (LiqSignal == GlobalVar.SignalSellPartialLiquid)
                    {
                        // 매도 부분 익절
                        m_TotalSigMan.SetSignalInfo(m_PriceStateList.Count, GlobalVar.SignalSellPartialLiquid, GlobalVar.SignalStateLiquid, ref m_CurState);
                        m_TotalSigMan.WriteSignalLog("매도 부분 청산 신호 발생", m_LogFileName, m_CurState);
                        SetSigState(ref m_CurState, null, null);
                        return m_CurState;
                    }
                }
            }
            else
            {
                // 고점에서 출발하여 내려오고 있는 상태이므로 매도 준비
                if (m_FutSignal.SigType == GlobalVar.OpSignalHighBegin /*&& m_K200Signal.SigType == GlobalVar.OpSignalHighBegin*/)
                {
                    int callCount = m_CallStateWatcher.CollectHighBeginSignal(GlobalVar.OpCallMode);
                    int putCount = m_PutStateWatcher.CollectLowBeginSignal(GlobalVar.OpPutMode);
                    int callMPCount = m_CallStateWatcher.OptSigMPCount;
                    int putMPCount = m_PutStateWatcher.OptSigMPCount;

                    if (callCount >= 2)
                    {
                        if (putCount >= 1)
                        {
                            if (callMPCount + putMPCount >= 3) // 주요가격에 의한 신호 발생
                            {
                                // 매도
                                m_TotalSigMan.SetSignalInfo(m_PriceStateList.Count, GlobalVar.SignalSell, GlobalVar.SignalStateTrans, ref m_CurState);
                                SetSigState(ref m_CurState, null, null);
                                m_TotalSigMan.WriteStateLog("매도로상태전환", m_LogFileName, m_CurState);
                                return m_CurState;
                            }
                            else // 월고나 옵션 시고시저에 의한 신호 발생
                            {
                                if (m_K200Signal.SigType == GlobalVar.OpSignalHighBegin)
                                {
                                    // 매도
                                    m_TotalSigMan.SetSignalInfo(m_PriceStateList.Count, GlobalVar.SignalSell, GlobalVar.SignalStateTrans, ref m_CurState);
                                    SetSigState(ref m_CurState, null, null);
                                    m_TotalSigMan.WriteStateLog("매도로상태전환", m_LogFileName, m_CurState);
                                    return m_CurState;
                                }
                            }
                        }
                    }
                    else if (callCount >= 1)
                    {
                        if (putCount >= 2)
                        {
                            if (callMPCount + putMPCount >= 3)
                            {
                                // 매도
                                m_TotalSigMan.SetSignalInfo(m_PriceStateList.Count, GlobalVar.SignalSell, GlobalVar.SignalStateTrans, ref m_CurState);
                                SetSigState(ref m_CurState, null, null);
                                m_TotalSigMan.WriteStateLog("매도로상태전환", m_LogFileName, m_CurState);
                                return m_CurState;
                            }
                            else
                            {
                                if (m_K200Signal.SigType == GlobalVar.OpSignalHighBegin)
                                {
                                    // 매도
                                    m_TotalSigMan.SetSignalInfo(m_PriceStateList.Count, GlobalVar.SignalSell, GlobalVar.SignalStateTrans, ref m_CurState);
                                    SetSigState(ref m_CurState, null, null);
                                    m_TotalSigMan.WriteStateLog("매도로상태전환", m_LogFileName, m_CurState);
                                    return m_CurState;
                                }
                            }
                        }
                    }
                }

                // 저점에서 출발하여 올라오고 있는 상태이므로 매수 준비
                if (m_FutSignal.SigType == GlobalVar.OpSignalLowBegin /*&& m_K200Signal.SigType == GlobalVar.OpSignalLowBegin*/)
                {
                    int callCount = m_CallStateWatcher.CollectLowBeginSignal(GlobalVar.OpCallMode);
                    int putCount = m_PutStateWatcher.CollectHighBeginSignal(GlobalVar.OpPutMode);
                    int callMPCount = m_CallStateWatcher.OptSigMPCount;
                    int putMPCount = m_PutStateWatcher.OptSigMPCount;
                    if (callCount >= 2)
                    {
                        if (putCount >= 1)
                        {
                            if (callMPCount + putMPCount >= 2)
                            {
                                // 매수
                                m_TotalSigMan.SetSignalInfo(m_PriceStateList.Count, GlobalVar.SignalBuy, GlobalVar.SignalStateTrans, ref m_CurState);
                                SetSigState(ref m_CurState, null, null);
                                m_TotalSigMan.WriteStateLog("매수로상태전환", m_LogFileName, m_CurState);
                                return m_CurState;
                            }
                            else
                            {
                                if (m_K200Signal.SigType == GlobalVar.OpSignalLowBegin)
                                {
                                    // 매수
                                    m_TotalSigMan.SetSignalInfo(m_PriceStateList.Count, GlobalVar.SignalBuy, GlobalVar.SignalStateTrans, ref m_CurState);
                                    SetSigState(ref m_CurState, null, null);
                                    m_TotalSigMan.WriteStateLog("매수로상태전환", m_LogFileName, m_CurState);
                                    return m_CurState;
                                }
                            }
                        }
                    }
                    else if (callCount >= 1)
                    {
                        if (putCount >= 2)
                        {
                            if (callMPCount + putMPCount >= 2)
                            {
                                // 매수
                                m_TotalSigMan.SetSignalInfo(m_PriceStateList.Count, GlobalVar.SignalBuy, GlobalVar.SignalStateTrans, ref m_CurState);
                                SetSigState(ref m_CurState, null, null);
                                m_TotalSigMan.WriteStateLog("매수로상태전환", m_LogFileName, m_CurState);
                                return m_CurState;
                            }
                            else
                            {
                                if (m_K200Signal.SigType == GlobalVar.OpSignalLowBegin)
                                {
                                    // 매수
                                    m_TotalSigMan.SetSignalInfo(m_PriceStateList.Count, GlobalVar.SignalBuy, GlobalVar.SignalStateTrans, ref m_CurState);
                                    SetSigState(ref m_CurState, null, null);
                                    m_TotalSigMan.WriteStateLog("매수로상태전환", m_LogFileName, m_CurState);
                                    return m_CurState;
                                }
                            }
                        }
                    }
                }
            }

            return null;
        }

        // 상태를 바탕으로 신호를 발생시킨다.
        private void CheckSignal()
        {
            if (OptMainPriceSysVar.LastSignalFired == true)
                return;

            EasyTrader.Signal.PriceSignal lastState = m_TotalSigMan.GetLastSignal(m_PriceStateList);
            if (lastState == null)
                return;

            // 먼저 상태 개수를 확인한다.
            // 정해진 상태 개수 안에서만 신호를 발생시킨다.
            int stateCount = m_PriceStateList.Count;
            //if (stateCount < OptMainPriceSysVar.SysStartState ||
            //    stateCount > OptMainPriceSysVar.SysEndState)
            //   return;

            string fCode = m_TotalSigMan.EasyTraderDataSet.DownLoader.GetFutureCode();
            string oCode = FindOpOrderCode(lastState.Type);
            // 먼저 청산을 확인한다.
            // 가격에 의한 청산 신호가 있는지 확인한다.
            EasyTrader.Signal.PriceSignal curSignal = GetLiquidSignalByTotalPrice();
            EasyTrader.Signal.PriceSignal activeSignal = null;
            if (curSignal != null)
            {
                activeSignal = m_TotalSigMan.CheckAddSignal(m_PriceSignalList, curSignal);
                if (OptMainPriceSysVar.OrderTarget == GlobalVar.OrderTargetFuture)
                {
                    if (fCode != "")
                        SendOrder(activeSignal, fCode, GlobalVar.OrderTargetFuture);
                }
                else
                {
                    if (oCode != "")
                        SendOrder(activeSignal, oCode, GlobalVar.OrderTargetOption);
                }
                OptMainPriceSysVar.AutoOrder = false;
                OptMainPriceSysVar.LastSignalFired = true;
                m_TotalSigMan.FireLastSignal(OptMainPriceSysVar.AutoOrder, GlobalVar.SysTypeOptPrice);
            }
            curSignal = GetLiquidSignalByMaxPrice();
            if (curSignal != null)
            {
                activeSignal = m_TotalSigMan.CheckAddSignal(m_PriceSignalList, curSignal);
                if (OptMainPriceSysVar.OrderTarget == GlobalVar.OrderTargetFuture)
                {
                    if (fCode != "")
                        SendOrder(activeSignal, fCode, GlobalVar.OrderTargetFuture);
                }
                else
                {
                    if (oCode != "")
                        SendOrder(activeSignal, oCode, GlobalVar.OrderTargetOption);
                }
                OptMainPriceSysVar.AutoOrder = false;
                OptMainPriceSysVar.LastSignalFired = true;
                m_TotalSigMan.FireLastSignal(OptMainPriceSysVar.AutoOrder, GlobalVar.SysTypeJisuWaveHogaSummit);
            }

            curSignal = GetLiquidSignalByTotalPriceStepByStep();
            if (curSignal != null)
            {
                activeSignal = m_TotalSigMan.CheckAddSignal(m_PriceSignalList, curSignal);
                //SendLiquidOrder(activeSignal);
                if (OptMainPriceSysVar.OrderTarget == GlobalVar.OrderTargetFuture)
                {
                    if (fCode != "")
                        SendOrder(activeSignal, fCode, GlobalVar.OrderTargetFuture);
                }
                else
                {
                    if (oCode != "")
                        SendOrder(activeSignal, oCode, GlobalVar.OrderTargetOption);
                }
                // 단계별 총 청산액을 증가시켜 준다.
                OptMainPriceSysVar.TotalProfitStepLiquidVal += OptMainPriceSysVar.StepLiquidVal;
            }

            curSignal = GetLiquidSignalByStateCountStepByStep();
            if (curSignal != null)
            {
                activeSignal = m_TotalSigMan.CheckAddSignal(m_PriceSignalList, curSignal);
                //SendLiquidOrder(activeSignal);
                if (OptMainPriceSysVar.OrderTarget == GlobalVar.OrderTargetFuture)
                {
                    if (fCode != "")
                        SendOrder(activeSignal, fCode, GlobalVar.OrderTargetFuture);
                }
                else
                {
                    if (oCode != "")
                        SendOrder(activeSignal, oCode, GlobalVar.OrderTargetOption);
                }
                // 단계별 상태값을 증가시켜 준다.
                OptMainPriceSysVar.StepLiquidStateCount++;
            }
            curSignal = GetLiquidSignalByPerPrice();
            if (curSignal != null)
            {
                activeSignal = m_TotalSigMan.CheckAddSignal(m_PriceSignalList, curSignal);
                if (OptMainPriceSysVar.OrderTarget == GlobalVar.OrderTargetFuture)
                {
                    if (fCode != "")
                        SendOrder(activeSignal, fCode, GlobalVar.OrderTargetFuture);
                }
                else
                {
                    if (oCode != "")
                        SendOrder(activeSignal, oCode, GlobalVar.OrderTargetOption);
                }
            }
            // 시간에 의한 청산 신호가 있는지 확인한다.
            curSignal = GetLiquidSignalByTime();
            if (curSignal != null)
            {
                activeSignal = m_TotalSigMan.CheckAddSignal(m_PriceSignalList, curSignal);
                //SendOrder(activeSignal);
                if (OptMainPriceSysVar.OrderTarget == GlobalVar.OrderTargetFuture)
                {
                    if (fCode != "")
                        SendOrder(activeSignal, fCode, GlobalVar.OrderTargetFuture);
                }
                else
                {
                    if (oCode != "")
                        SendOrder(activeSignal, oCode, GlobalVar.OrderTargetOption);
                }
                OptMainPriceSysVar.AutoOrder = false;
                OptMainPriceSysVar.LastSignalFired = true;
                m_TotalSigMan.FireLastSignal(OptMainPriceSysVar.AutoOrder, GlobalVar.SysTypeOptPrice);
            }
            // 상태 개수에 의한 청산 신호가 있는지 확인한다.
            curSignal = GetLiquidSignalByStateCount();
            if (curSignal != null)
            {
                activeSignal = m_TotalSigMan.CheckAddSignal(m_PriceSignalList, curSignal);
                if (OptMainPriceSysVar.OrderTarget == GlobalVar.OrderTargetFuture)
                {
                    if (fCode != "")
                        SendOrder(activeSignal, fCode, GlobalVar.OrderTargetFuture);
                }
                else
                {
                    if (oCode != "")
                        SendOrder(activeSignal, oCode, GlobalVar.OrderTargetOption);
                }
                OptMainPriceSysVar.AutoOrder = false;
                OptMainPriceSysVar.LastSignalFired = true;
                m_TotalSigMan.FireLastSignal(OptMainPriceSysVar.AutoOrder, GlobalVar.SysTypeOptPrice);
            }
            // 붕괴 목록에 의한 신호가 있는지 확인한다.
            curSignal = GetSignalByBreakDownList();
            if (curSignal != null)
            {
                activeSignal = m_TotalSigMan.CheckAddSignal(m_PriceSignalList, curSignal);
                if (OptMainPriceSysVar.OrderTarget == GlobalVar.OrderTargetFuture)
                {
                    if (fCode != "")
                        SendOrder(activeSignal, fCode, GlobalVar.OrderTargetFuture);
                }
                else
                {
                    if (oCode != "")
                        SendOrder(activeSignal, oCode, GlobalVar.OrderTargetOption);
                }
            }
        }


        private EasyTrader.Signal.PriceSignal FindSameLiqDownSignal(string a_OpCode, double a_Val, int a_SigType)
        {
            int count = m_PriceSignalList.Count;
            if (count == 0)
                return null;

            for (int i = count - 1; i >= 0; i--)
            {
                EasyTrader.Signal.PriceSignal curSignal = m_PriceSignalList[i];
                if (curSignal.Type != a_SigType)
                {
                    return null;
                }

                if (curSignal.Type == a_SigType)
                {
                    if (curSignal.OptSigCode == a_OpCode && curSignal.OptSigVal == a_Val)
                        return curSignal;
                }
            }

            return null;
        }

        public EasyTrader.Signal.PriceSignal CheckAddSignal(PriceSignalList a_SignalList, EasyTrader.Signal.PriceSignal a_Signal)
        {
            if (a_Signal == null || a_SignalList == null)
                return null;
            int count = a_SignalList.Count;

            EasyTrader.Signal.PriceSignal newSignal = null;
            if (count <= 0)
            {
                newSignal = a_Signal.Clone();
                a_SignalList.Add(newSignal);
                return newSignal;
            }
            else
            {
                // 선물 본 신호로 필터링
                EasyTrader.Signal.PriceSignal prevSignal = a_SignalList[count - 1];
                if (prevSignal.Type == GlobalVar.SignalExitBuy || prevSignal.Type == GlobalVar.SignalExitSell)
                {
                    if (a_Signal.Type == GlobalVar.SignalExitBuy ||
                        a_Signal.Type == GlobalVar.SignalExitSell ||
                        a_Signal.Type == GlobalVar.SignalSellPartialLiquid ||
                        a_Signal.Type == GlobalVar.SignalBuyPartialLiquid)
                    {
                        return null;
                    }
                }

                if (prevSignal.OptSigCode != a_Signal.OptSigCode)
                {
                    if (a_Signal.Type == GlobalVar.SignalSellPartialLiquid ||
                    a_Signal.Type == GlobalVar.SignalBuyPartialLiquid)
                    {
                        EasyTrader.Signal.PriceSignal sameSignal = FindSameLiqDownSignal(a_Signal.OptSigCode, a_Signal.OptSigVal, a_Signal.Type);
                        if (sameSignal == null)
                        {
                            newSignal = a_Signal.Clone();
                            a_SignalList.Add(newSignal);
                            return newSignal;
                        }
                    }
                    else
                    {
                        newSignal = a_Signal.Clone();
                        a_SignalList.Add(newSignal);
                        return newSignal;
                    }
                }
                else
                {
                    if (prevSignal.OptSigType != a_Signal.OptSigType)
                    {
                        newSignal = a_Signal.Clone();
                        a_SignalList.Add(newSignal);
                        return newSignal;
                    }
                    else
                    {
                        if (prevSignal.OptSigVal != a_Signal.OptSigVal)
                        {
                            newSignal = a_Signal.Clone();
                            a_SignalList.Add(newSignal);
                            return newSignal;
                        }
                    }
                }
            }

            return null;
        }

        private EasyTrader.Signal.PriceSignal GetSignalByBreakDownList()
        {
            EasyTrader.Signal.PriceSignal lastState = m_TotalSigMan.GetLastSignal(m_PriceStateList);
            if (lastState == null)
                return null;

            
            if (lastState.Type == GlobalVar.SignalExitBuy)
            {
                m_TotalSigMan.SetSignalInfo(m_CurIndex, m_PriceStateList.Count, GlobalVar.SignalExitBuy, GlobalVar.SignalStateLiquid, ref m_CurState);
                m_TotalSigMan.WriteSignalLog("매수 청산 신호 발생", m_LogFileName, m_CurState);
                return m_CurState;
            }
            else if (lastState.Type == GlobalVar.SignalExitSell)
            {
                m_TotalSigMan.SetSignalInfo(m_CurIndex, m_PriceStateList.Count, GlobalVar.SignalExitSell, GlobalVar.SignalStateLiquid, ref m_CurState);
                m_TotalSigMan.WriteSignalLog("매도 청산 신호 발생", m_LogFileName, m_CurState);
                return m_CurState;
            }
            else if (lastState.Type == GlobalVar.SignalSell)
            {
                m_TotalSigMan.SetSignalInfo(m_CurIndex, m_PriceStateList.Count, GlobalVar.SignalSell, GlobalVar.SignalStateTrans, ref m_CurState);
                m_TotalSigMan.WriteSignalLog("매도 전환 신호 발생", m_LogFileName, m_CurState);
                return m_CurState;
            }
            else if (lastState.Type == GlobalVar.SignalBuy) 
            {
                m_TotalSigMan.SetSignalInfo(m_CurIndex, m_PriceStateList.Count, GlobalVar.SignalBuy, GlobalVar.SignalStateTrans, ref m_CurState);
                m_TotalSigMan.WriteSignalLog("매수 전환 신호 발생", m_LogFileName, m_CurState);
                return m_CurState;
            }
            else if (lastState.Type == GlobalVar.SignalSellPartialLiquid)
            {
                m_TotalSigMan.SetSignalInfo(m_CurIndex, m_PriceStateList.Count, GlobalVar.SignalSell, GlobalVar.SignalStateTrans, ref m_CurState);
                m_TotalSigMan.WriteSignalLog("매도 일부청산 신호 발생", m_LogFileName, m_CurState);
                return m_CurState;
            }
            else if (lastState.Type == GlobalVar.SignalBuyPartialLiquid)
            {
                m_TotalSigMan.SetSignalInfo(m_CurIndex, m_PriceStateList.Count, GlobalVar.SignalBuy, GlobalVar.SignalStateTrans, ref m_CurState);
                m_TotalSigMan.WriteSignalLog("매수 일부청산 신호 발생", m_LogFileName, m_CurState);
                return m_CurState;
            }

            return null;
        }

        public void ClearState()
        {
            OpStateList stateList = m_CallStateWatcher.StateList;
            for (int i = 0; i < stateList.Count; i++)
            {
                EasyTrader.Option.StateWatcher watcher = stateList[i];
                // 먼저 상태를 초기화 한다.
                watcher.ClearState();
            }

            m_CallStateWatcher.ClearBreakVal();

            stateList = m_PutStateWatcher.StateList;
            for (int i = 0; i < stateList.Count; i++)
            {
                EasyTrader.Option.StateWatcher watcher = stateList[i];
                // 먼저 상태를 초기화 한다.
                watcher.ClearState();
            }

            m_PutStateWatcher.ClearBreakVal();
        }


        // 단계별로 청산 값을 적용해 본다.
        protected EasyTrader.Signal.PriceSignal GetLiquidSignalByStep()
        {
            EasyTrader.Signal.PriceSignal lastSignal = m_TotalSigMan.GetLastSignal(m_PriceSignalList);
            // 가장 최근의 상태를 가져 온다. 이 상태를 바탕으로 새로운 신호를 만들어 낸다.
            EasyTrader.Signal.PriceSignal lastState = m_TotalSigMan.GetLastSignal(m_PriceStateList);
            if (lastState == null)
                return null;
            // 현재 상태 번호를 구한다.
            int curStateNumber = m_PriceStateList.Count;
            if (lastSignal != null)
            {
                // 이전 신호와 현재 신호 타입이 같을 때는 아무일도 하지 않는다.
                if (lastSignal.Type == lastState.Type)
                    return null;
            }

            int signalVal = GlobalVar.SignalNone;
            if (lastState.Type == GlobalVar.SignalBuy)
            {
                /*
                signalVal = GlobalVar.SignalBuy;
                m_TotalSigMan.SetSignalInfo(m_PriceStateList.Count, signalVal, GlobalVar.SignalStateTrans, ref m_CurState);
                m_TotalSigMan.WriteSignalLog("매수 전환 신호 발생", m_LogFileName, m_CurState);
                 */
                for (int i = 0; i < m_CallStateWatcher.UpTargetList.Count; i++)
                {
                    EasyTrader.Option.CompVal curCompVal = m_CallStateWatcher.UpTargetList[i];
                    // 비교할 값이 0일 때는 아무일도 하지 않는다.
                    if (curCompVal.Val == 0.0)
                        continue;

                    double outClose = 0.0;
                    int sameValCount = curCompVal.Watcher.GetHighLowSameValueCount(m_CurIndex, 10, 1, out outClose);
                    // 목표값과 현재값의 차이를 구한다.
                    double deltaTarget = outClose - curCompVal.Val;
                    if (outClose == curCompVal.Val)
                    {
                        if (deltaTarget > 0)
                        {
                            if (sameValCount < 3) // 동일한 값이 2개 이하 일때
                            {
                                // 동일한 값이 2개 이하인데 이미 목표값을 넘었을 경우에는 시간상으로 넘은 시간이 3분 경과한 후에 청산을 내보낸다. 
                                int timeGap = m_CurIndex - curCompVal.Watcher.BreakUpIndex;
                                if (timeGap >= 3)
                                {
                                    // 같은 상태에서 청산이 여러번 일어 날 수 있기 때문에 이 부분은 단계별 청산을 만들어 다시 적용해야 한다.
                                    m_TotalSigMan.SetSignalInfo(m_PriceStateList.Count, GlobalVar.SignalExitBuy, GlobalVar.SignalStateLiquid, ref m_CurState);
                                    m_TotalSigMan.WriteSignalLog("단계별 목표 도달에 의한 청산신호 발생", m_LogFileName, m_CurState);
                                    return m_CurState;
                                }
                            }
                        }
                        else
                        {
                            if (sameValCount >= 3) // 동일한 값이 3개 이상일 때
                            {
                                // 동일한 값이 3개 이상일 때는 목표값에서 확실한 저항이 있는 것으로 보고 바로 청산을 내보낸다.
                                // 같은 상태에서 청산이 여러번 일어 날 수 있기 때문에 이 부분은 단계별 청산을 만들어 다시 적용해야 한다.
                                m_TotalSigMan.SetSignalInfo(m_PriceStateList.Count, GlobalVar.SignalExitBuy, GlobalVar.SignalStateLiquid, ref m_CurState);
                                m_TotalSigMan.WriteSignalLog("단계별 목표 도달에 의한 청산신호 발생", m_LogFileName, m_CurState);
                                return m_CurState;
                            }
                        }
                    }
                }
                return m_CurState;
            }
            else if (lastState.Type == GlobalVar.SignalSell)
            {
                /*
                signalVal = GlobalVar.SignalSell;
                m_TotalSigMan.SetSignalInfo(m_PriceStateList.Count, signalVal, GlobalVar.SignalStateTrans, ref m_CurState);
                m_TotalSigMan.WriteSignalLog("매도 전환 신호 발생", m_LogFileName, m_CurState);
                 */
                for (int i = 0; i < m_PutStateWatcher.UpTargetList.Count; i++)
                {
                    EasyTrader.Option.CompVal curCompVal = m_PutStateWatcher.UpTargetList[i];
                    double outClose = 0.0;
                    int sameValCount = curCompVal.Watcher.GetHighLowSameValueCount(m_CurIndex, 10, 1, out outClose);
                    // 목표값과 현재값의 차이를 구한다.
                    double deltaTarget = outClose - curCompVal.Val;
                    if (sameValCount < 2) // 동일한 값이 1개 이하 일때
                    {
                        ;
                    }
                    else if (sameValCount < 3) // 동일한 값이 2개 이하 일 때
                    {
                        ;
                    }
                    else // 동일한 값이 3개 이상일 때
                    {
                        ;
                    }
                }
                return m_CurState;
            }

            return null;
        }


        public void UpdateSysState()
        {
            m_CurIndex = m_TotalSigMan.CurIndex;
            Console.WriteLine("OptSysIndex = " + m_CurIndex.ToString());
            // 옵션 가격을 일단 다 받고 등가가 확정된 뒤에 신호를 발생해 준다.
            if (m_TotalSigMan.EasyTraderDataSet.DownLoader.AllOptChartDataDownloaded == true &&
                m_TotalSigMan.EasyTraderDataSet.DownLoader.ATMChanged == true)
            {
                FindCurState();
                CheckSignal();
            }
        }
    }
}
